Shiny App Experiment Lab
Libraries
library(here)
library(dplyr)
library(arrow)
Reading data
census_dataset |> collect()
Reading specific data
pueb_norm <- census_dataset |>
filter(NOM_ENT=="Puebla") |>
collect()
Warning: Invalid metadata$rWarning: Invalid metadata$rWarning: Invalid metadata$rWarning: Invalid metadata$r
pueb_norm
unique(pueb_norm$NOM_MUN)
[1] "Total de la entidad Puebla" "Acajete" "Acateno" "Acatlán"
[5] "Acatzingo" "Acteopan" "Ahuacatlán" "Ahuatlán"
[9] "Ahuazotepec" "Ahuehuetitla" "Ajalpan" "Albino Zertuche"
[13] "Aljojuca" "Altepexi" "Amixtlán" "Amozoc"
[17] "Aquixtla" "Atempan" "Atexcal" "Atlixco"
[21] "Atoyatempan" "Atzala" "Atzitzihuacán" "Atzitzintla"
[25] "Axutla" "Ayotoxco de Guerrero" "Calpan" "Caltepec"
[29] "Camocuautla" "Caxhuacan" "Coatepec" "Coatzingo"
[33] "Cohetzala" "Cohuecan" "Coronango" "Coxcatlán"
[37] "Coyomeapan" "Coyotepec" "Cuapiaxtla de Madero" "Cuautempan"
[41] "Cuautinchán" "Cuautlancingo" "Cuayuca de Andrade" "Cuetzalan del Progreso"
[45] "Cuyoaco" "Chalchicomula de Sesma" "Chapulco" "Chiautla"
[49] "Chiautzingo" "Chiconcuautla" "Chichiquila" "Chietla"
[53] "Chigmecatitlán" "Chignahuapan" "Chignautla" "Chila"
[57] "Chila de la Sal" "Honey" "Chilchotla" "Chinantla"
[61] "Domingo Arenas" "Eloxochitlán" "Epatlán" "Esperanza"
[65] "Francisco Z. Mena" "General Felipe Ángeles" "Guadalupe" "Guadalupe Victoria"
[69] "Hermenegildo Galeana" "Huaquechula" "Huatlatlauca" "Huauchinango"
[73] "Huehuetla" "Huehuetlán el Chico" "Huejotzingo" "Hueyapan"
[77] "Hueytamalco" "Hueytlalpan" "Huitzilan de Serdán" "Huitziltepec"
[81] "Atlequizayan" "Ixcamilpa de Guerrero" "Ixcaquixtla" "Ixtacamaxtitlán"
[85] "Ixtepec" "Izúcar de Matamoros" "Jalpan" "Jolalpan"
[89] "Jonotla" "Jopala" "Juan C. Bonilla" "Juan Galindo"
[93] "Juan N. Méndez" "Lafragua" "Libres" "La Magdalena Tlatlauquitepec"
[97] "Mazapiltepec de Juárez" "Mixtla" "Molcaxac" "Cañada Morelos"
[101] "Naupan" "Nauzontla" "Nealtican" "Nicolás Bravo"
[105] "Nopalucan" "Ocotepec" "Ocoyucan" "Olintla"
[109] "Oriental" "Pahuatlán" "Palmar de Bravo" "Pantepec"
[113] "Petlalcingo" "Piaxtla" "Puebla" "Quecholac"
[117] "Quimixtlán" "Rafael Lara Grajales" "Los Reyes de Juárez" "San Andrés Cholula"
[121] "San Antonio Cañada" "San Diego la Mesa Tochimiltzingo" "San Felipe Teotlalcingo" "San Felipe Tepatlán"
[125] "San Gabriel Chilac" "San Gregorio Atzompa" "San Jerónimo Tecuanipan" "San Jerónimo Xayacatlán"
[129] "San José Chiapa" "San José Miahuatlán" "San Juan Atenco" "San Juan Atzompa"
[133] "San Martín Texmelucan" "San Martín Totoltepec" "San Matías Tlalancaleca" "San Miguel Ixitlán"
[137] "San Miguel Xoxtla" "San Nicolás Buenos Aires" "San Nicolás de los Ranchos" "San Pablo Anicano"
[141] "San Pedro Cholula" "San Pedro Yeloixtlahuaca" "San Salvador el Seco" "San Salvador el Verde"
[145] "San Salvador Huixcolotla" "San Sebastián Tlacotepec" "Santa Catarina Tlaltempan" "Santa Inés Ahuatempan"
[149] "Santa Isabel Cholula" "Santiago Miahuatlán" "Huehuetlán el Grande" "Santo Tomás Hueyotlipan"
[153] "Soltepec" "Tecali de Herrera" "Tecamachalco" "Tecomatlán"
[157] "Tehuacán" "Tehuitzingo" "Tenampulco" "Teopantlán"
[161] "Teotlalco" "Tepanco de López" "Tepango de Rodríguez" "Tepatlaxco de Hidalgo"
[165] "Tepeaca" "Tepemaxalco" "Tepeojuma" "Tepetzintla"
[169] "Tepexco" "Tepexi de Rodríguez" "Tepeyahualco" "Tepeyahualco de Cuauhtémoc"
[173] "Tetela de Ocampo" "Teteles de Avila Castillo" "Teziutlán" "Tianguismanalco"
[177] "Tilapa" "Tlacotepec de Benito Juárez" "Tlacuilotepec" "Tlachichuca"
[181] "Tlahuapan" "Tlaltenango" "Tlanepantla" "Tlaola"
[185] "Tlapacoya" "Tlapanalá" "Tlatlauquitepec" "Tlaxco"
[189] "Tochimilco" "Tochtepec" "Totoltepec de Guerrero" "Tulcingo"
[193] "Tuzamapan de Galeana" "Tzicatlacoyan" "Venustiano Carranza" "Vicente Guerrero"
[197] "Xayacatlán de Bravo" "Xicotepec" "Xicotlán" "Xiutetelco"
[201] "Xochiapulco" "Xochiltepec" "Xochitlán de Vicente Suárez" "Xochitlán Todos Santos"
[205] "Yaonáhuac" "Yehualtepec" "Zacapala" "Zacapoaxtla"
[209] "Zacatlán" "Zapotitlán" "Zapotitlán de Méndez" "Zaragoza"
[213] "Zautla" "Zihuateutla" "Zinacatepec" "Zongozotla"
[217] "Zoquiapan" "Zoquitlán"
Example
extract_coordinates <- function(data, municipality, locality) {
selected_location <- data |>
filter(NOM_MUN == municipality, NOM_LOC == locality)
coordinates <- tibble(
long = selected_location$longitude_decimal,
lat = selected_location$latitude_decimal
)
return(coordinates)
}
municipality <- "Acajete"
locality <- "Santa Isabel Tepetzala"
red_point <- extract_coordinates(pueb_norm, municipality, locality) |>
slice(1)
# red_point <- data.frame(long = -98.2035, lat = 19.0414)
filtered_geojson <- geojson_file |>
filter(name == "Puebla")
Error: object 'geojson_file' not found
Getting column names
column_names <- names(pueb_norm)
column_names
[1] "ENTIDAD" "MUN" "NOM_MUN" "LOC" "NOM_LOC" "LONGITUD" "LATITUD"
[8] "ALTITUD" "POBTOT" "POBFEM" "POBMAS" "REL_H_M" "POB0_14" "POB15_64"
[15] "POB65_MAS" "P_0A4" "P_0A4_F" "P_0A4_M" "P_5A9" "P_5A9_F" "P_5A9_M"
[22] "P_10A14" "P_10A14_F" "P_10A14_M" "P_15A19" "P_15A19_F" "P_15A19_M" "P_20A24"
[29] "P_20A24_F" "P_20A24_M" "P_25A29" "P_25A29_F" "P_25A29_M" "P_30A34" "P_30A34_F"
[36] "P_30A34_M" "P_35A39" "P_35A39_F" "P_35A39_M" "P_40A44" "P_40A44_F" "P_40A44_M"
[43] "P_45A49" "P_45A49_F" "P_45A49_M" "P_50A54" "P_50A54_F" "P_50A54_M" "P_55A59"
[50] "P_55A59_F" "P_55A59_M" "P_60A64" "P_60A64_F" "P_60A64_M" "P_65A69" "P_65A69_F"
[57] "P_65A69_M" "P_70A74" "P_70A74_F" "P_70A74_M" "P_75A79" "P_75A79_F" "P_75A79_M"
[64] "P_80A84" "P_80A84_F" "P_80A84_M" "P_85YMAS" "P_85YMAS_F" "P_85YMAS_M" "PROM_HNV"
[71] "PNACENT" "PNACENT_F" "PNACENT_M" "PNACOE" "PNACOE_F" "PNACOE_M" "PRES2015"
[78] "PRES2015_F" "PRES2015_M" "PRESOE15" "PRESOE15_F" "PRESOE15_M" "P3YM_HLI" "P3YM_HLI_F"
[85] "P3YM_HLI_M" "P3HLINHE" "P3HLINHE_F" "P3HLINHE_M" "P3HLI_HE" "P3HLI_HE_F" "P3HLI_HE_M"
[92] "PHOG_IND" "POB_AFRO" "POB_AFRO_F" "POB_AFRO_M" "PCON_DISC" "PCON_LIMI" "PSIND_LIM"
[99] "P3A5_NOA" "P3A5_NOA_F" "P3A5_NOA_M" "P6A11_NOA" "P6A11_NOAF" "P6A11_NOAM" "P12A14NOA"
[106] "P12A14NOAF" "P12A14NOAM" "P15A17A" "P15A17A_F" "P15A17A_M" "P18A24A" "P18A24A_F"
[113] "P18A24A_M" "P8A14AN" "P8A14AN_F" "P8A14AN_M" "P15YM_AN" "P15YM_AN_F" "P15YM_AN_M"
[120] "P15YM_SE" "P15YM_SE_F" "P15YM_SE_M" "P15PRI_IN" "P15PRI_INF" "P15PRI_INM" "P15PRI_CO"
[127] "P15PRI_COF" "P15PRI_COM" "P15SEC_IN" "P15SEC_INF" "P15SEC_INM" "P15SEC_CO" "P15SEC_COF"
[134] "P15SEC_COM" "P18YM_PB" "P18YM_PB_F" "P18YM_PB_M" "GRAPROES" "GRAPROES_F" "GRAPROES_M"
[141] "PEA" "PEA_F" "PEA_M" "PE_INAC" "PE_INAC_F" "PE_INAC_M" "POCUPADA"
[148] "POCUPADA_F" "POCUPADA_M" "PDESOCUP" "PDESOCUP_F" "PDESOCUP_M" "PSINDER" "PDER_SS"
[155] "P12YM_SOLT" "P12YM_CASA" "P12YM_SEPA" "PCATOLICA" "PRO_CRIEVA" "POTRAS_REL" "PSIN_RELIG"
[162] "TOTHOG" "HOGJEF_F" "HOGJEF_M" "POBHOG" "PHOGJEF_F" "PHOGJEF_M" "longitude_decimal"
[169] "latitude_decimal" "NOM_ENT"
Getting column names that have to do with population age cohorts
(Masculine/Feminine)
matching_columns <- grep("^P_.*[MF]$", column_names, value = TRUE)
matching_columns
[1] "P_0A4_F" "P_0A4_M" "P_5A9_F" "P_5A9_M" "P_10A14_F" "P_10A14_M" "P_15A19_F" "P_15A19_M" "P_20A24_F" "P_20A24_M" "P_25A29_F"
[12] "P_25A29_M" "P_30A34_F" "P_30A34_M" "P_35A39_F" "P_35A39_M" "P_40A44_F" "P_40A44_M" "P_45A49_F" "P_45A49_M" "P_50A54_F" "P_50A54_M"
[23] "P_55A59_F" "P_55A59_M" "P_60A64_F" "P_60A64_M" "P_65A69_F" "P_65A69_M" "P_70A74_F" "P_70A74_M" "P_75A79_F" "P_75A79_M" "P_80A84_F"
[34] "P_80A84_M" "P_85YMAS_F" "P_85YMAS_M"
Separate by sex
ending_in_M <- character(0)
ending_in_F <- character(0)
# Iterate over the matching column names and separate into M or F vectors
for (col_name in matching_columns) {
if (endsWith(col_name, "M")) {
ending_in_M <- c(ending_in_M, col_name)
} else if (endsWith(col_name, "F")) {
ending_in_F <- c(ending_in_F, col_name)
}
}
# Print the vectors
print("Column names ending in M:")
[1] "Column names ending in M:"
print(ending_in_M)
[1] "P_0A4_M" "P_5A9_M" "P_10A14_M" "P_15A19_M" "P_20A24_M" "P_25A29_M" "P_30A34_M" "P_35A39_M" "P_40A44_M" "P_45A49_M" "P_50A54_M"
[12] "P_55A59_M" "P_60A64_M" "P_65A69_M" "P_70A74_M" "P_75A79_M" "P_80A84_M" "P_85YMAS_M"
print("Column names ending in F:")
[1] "Column names ending in F:"
print(ending_in_F)
[1] "P_0A4_F" "P_5A9_F" "P_10A14_F" "P_15A19_F" "P_20A24_F" "P_25A29_F" "P_30A34_F" "P_35A39_F" "P_40A44_F" "P_45A49_F" "P_50A54_F"
[12] "P_55A59_F" "P_60A64_F" "P_65A69_F" "P_70A74_F" "P_75A79_F" "P_80A84_F" "P_85YMAS_F"
library(ggplot2)
library(dplyr)
cohort_names_m <- c("P_0A4_M",
"P_5A9_M",
"P_10A14_M",
"P_15A19_M",
"P_20A24_M",
"P_25A29_M",
"P_30A34_M",
"P_35A39_M",
"P_40A44_M",
"P_45A49_M",
"P_50A54_M",
"P_55A59_M",
"P_60A64_M",
"P_65A69_M",
"P_70A74_M",
"P_75A79_M",
"P_80A84_M",
"P_85YMAS_M")
cohort_names_f <- c("P_0A4_F",
"P_5A9_F",
"P_10A14_F",
"P_15A19_F",
"P_20A24_F",
"P_25A29_F",
"P_30A34_F",
"P_35A39_F",
"P_40A44_F",
"P_45A49_F",
"P_50A54_F",
"P_55A59_F",
"P_60A64_F",
"P_65A69_F",
"P_70A74_F",
"P_75A79_F",
"P_80A84_F",
"P_85YMAS_F")
municipality <- "Acajete"
locality <- "San Javier"
pueb_norm_filt <- pueb_norm |>
filter(NOM_MUN == municipality, NOM_LOC == locality)
cohort_counts_m <- as.numeric(pueb_norm_filt[1,cohort_names_m])
cohort_counts_f <- as.numeric(pueb_norm_filt[1,cohort_names_f])
data <- tibble(
Cohort = c(cohort_names_m, cohort_names_f),
Count = c(cohort_counts_m, cohort_counts_f),
Sex = rep(c("Male", "Female"), each = length(cohort_names_m))
)
# Plotting population pyramid
ggplot(data, aes(x = reorder(Cohort, -Count), y = Count, fill = Sex)) +
geom_bar(stat = "identity", position = "identity") +
scale_fill_manual(values = c("blue", "pink")) +
coord_flip() +
labs(title = "Population Pyramid",
x = "Population Count",
y = "Age Cohort",
fill = "Sex") +
theme_minimal()

new_ages <- c("0-4",
"5-9",
"10-14",
"15-19",
"20-24",
"25-29",
"30-34",
"35-39",
"40-44",
"45-49",
"50-54",
"55-59",
"60-64",
"65-69",
"70-74",
"75-79",
"80-84",
"85+")
data <- tibble(
Age = paste0(new_ages),
Male = sample(200:1000, length(cohort_names_m), replace = TRUE),
Female = sample(200:1000, length(cohort_names_f), replace = TRUE)
)
data_long <- pivot_longer(
data,
cols = c(Male, Female),
names_to = "Sex",
values_to = "Population"
)
basic_plot <- ggplot(data_long, aes(x = Age, y = ifelse(Sex == "Male", -Population, Population), fill = Sex)) +
geom_bar(stat = "identity") +
scale_y_continuous(labels = abs, limits = max(data_long$Population) * c(-1, 1)) +
coord_flip() +
theme_minimal() +
labs(x = "Age", y = "Population", fill = "Sex", title = "Population Pyramid")
basic_plot

Complete pipeline
census_dataset <- open_dataset(here("data", "processed", "parquet_data_coords"))
pueb_norm <- census_dataset |>
filter(NOM_ENT=="Puebla") |>
collect()
Warning: Invalid metadata$rWarning: Invalid metadata$rWarning: Invalid metadata$rWarning: Invalid metadata$r
municipality <- "Acajete"
locality <- "San Javier"
pueb_norm_filt <- pueb_norm |>
filter(NOM_MUN == municipality, NOM_LOC == locality)
cohort_names_m <- c("P_0A4_M",
"P_5A9_M",
"P_10A14_M",
"P_15A19_M",
"P_20A24_M",
"P_25A29_M",
"P_30A34_M",
"P_35A39_M",
"P_40A44_M",
"P_45A49_M",
"P_50A54_M",
"P_55A59_M",
"P_60A64_M",
"P_65A69_M",
"P_70A74_M",
"P_75A79_M",
"P_80A84_M",
"P_85YMAS_M")
cohort_names_f <- c("P_0A4_F",
"P_5A9_F",
"P_10A14_F",
"P_15A19_F",
"P_20A24_F",
"P_25A29_F",
"P_30A34_F",
"P_35A39_F",
"P_40A44_F",
"P_45A49_F",
"P_50A54_F",
"P_55A59_F",
"P_60A64_F",
"P_65A69_F",
"P_70A74_F",
"P_75A79_F",
"P_80A84_F",
"P_85YMAS_F")
new_ages <- c("0-4",
"5-9",
"10-14",
"15-19",
"20-24",
"25-29",
"30-34",
"35-39",
"40-44",
"45-49",
"50-54",
"55-59",
"60-64",
"65-69",
"70-74",
"75-79",
"80-84",
"85+")
data <- tibble(
Age = paste0(new_ages),
Male = as.numeric(pueb_norm_filt[1,cohort_names_m]),
Female = as.numeric(pueb_norm_filt[1,cohort_names_f])
)
data_long <- pivot_longer(
data,
cols = c(Male, Female),
names_to = "Sex",
values_to = "Population"
)
basic_plot <- ggplot(data_long, aes(x = Age, y = ifelse(Sex == "Male", -Population, Population), fill = Sex)) +
geom_bar(stat = "identity") +
scale_y_continuous(labels = abs, limits = max(data_long$Population) * c(-1, 1)) +
coord_flip() +
theme_minimal() +
labs(x = "Age", y = "Population", fill = "Sex", title = "Population Pyramid")
basic_plot

Card
# card <- census_dataset |>
# filter(
# NOM_ENT == "Puebla",
# NOM_MUN == "Acateno",
# NOM_LOC == "Santa Andrea"
# ) |>
# collect()
total_population <- as.numeric(card[1, c("POBTOT")], na.rm = TRUE)
paste("Total Population:", total_population)
[1] "Total Population: 1"
Pie
tot <- census_dataset |>
filter(NOM_ENT=="Total nacional") |>
collect()
Warning: Invalid metadata$rWarning: Invalid metadata$rWarning: Invalid metadata$rWarning: Invalid metadata$r
tot
# origin <- census_dataset |>
# filter(
# NOM_ENT == "Puebla",
# NOM_MUN == "Acateno",
# NOM_LOC == "Santa Andrea"
# ) |>
# collect()
tot
# Extract birth data
birth_local <- as.numeric(tot[1, "PNACENT"])
birth_another <- as.numeric(tot[1, "PNACOE"])
# Debugging output
print(paste("Birth Local:", birth_local))
[1] "Birth Local: 102724322"
print(paste("Birth Another:", birth_another))
[1] "Birth Another: 21611963"
# Create ratio dataframe
ratio_df <- tibble(
Category = c("Local", "Other"),
Ratio = c(birth_local, birth_another)
)
# Calculate percentages
ratio_df$Percentage <- ratio_df$Ratio / sum(ratio_df$Ratio) * 100
# Plot the pie chart
gg <- ggplot(ratio_df, aes(x = "", y = Ratio, fill = Category)) +
geom_bar(stat = "identity", width = 1) +
coord_polar(theta = "y") +
theme_void() +
theme(legend.position = "bottom") +
scale_fill_manual(values = c("#00BFC4", "#F8766D")) +
geom_text(aes(label = paste0(round(Percentage), "%")),
position = position_stack(vjust = 0.5),
size = 5, color = "white", fontface = "bold")
gg

NA
LS0tDQp0aXRsZTogIlIgTm90ZWJvb2siDQpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sNCmF1dGhvcjogTWFyY28gUG9sbyBCcmF2byBNb250aWVsDQpkYXRlOiAyMDIwLTA0LTIzDQotLS0NCg0KIyBTaGlueSBBcHAgRXhwZXJpbWVudCBMYWINCg0KIyMjIExpYnJhcmllcw0KDQpgYGB7cn0NCmxpYnJhcnkoaGVyZSkNCmxpYnJhcnkoZHBseXIpDQpsaWJyYXJ5KGFycm93KQ0KYGBgDQoNCiMjIyBSZWFkaW5nIGRhdGENCg0KYGBge3J9DQpjZW5zdXNfZGF0YXNldCA8LSBvcGVuX2RhdGFzZXQoaGVyZSgiZGF0YSIsICJwcm9jZXNzZWQiLCAicGFycXVldF9kYXRhX2Nvb3JkcyIpKQ0KY2Vuc3VzX2RhdGFzZXQNCg0KYGBgDQoNCiMjIyBSZWFkaW5nIHNwZWNpZmljIGRhdGENCg0KYGBge3J9DQpwdWViX25vcm0gPC0gY2Vuc3VzX2RhdGFzZXQgfD4NCiAgICBmaWx0ZXIoTk9NX0VOVD09IlB1ZWJsYSIpIHw+IA0KICAgIGNvbGxlY3QoKQ0KDQpwdWViX25vcm0NCmBgYA0KDQpgYGB7cn0NCnVuaXF1ZShwdWViX25vcm0kTk9NX01VTikNCmBgYA0KDQojIyMgRXhhbXBsZQ0KDQpgYGB7cn0NCmV4dHJhY3RfY29vcmRpbmF0ZXMgPC0gZnVuY3Rpb24oZGF0YSwgbXVuaWNpcGFsaXR5LCBsb2NhbGl0eSkgew0KICBzZWxlY3RlZF9sb2NhdGlvbiA8LSBkYXRhIHw+IA0KICAgIGZpbHRlcihOT01fTVVOID09IG11bmljaXBhbGl0eSwgTk9NX0xPQyA9PSBsb2NhbGl0eSkNCiAgDQogIGNvb3JkaW5hdGVzIDwtIHRpYmJsZSgNCiAgICBsb25nID0gc2VsZWN0ZWRfbG9jYXRpb24kbG9uZ2l0dWRlX2RlY2ltYWwsDQogICAgbGF0ID0gc2VsZWN0ZWRfbG9jYXRpb24kbGF0aXR1ZGVfZGVjaW1hbA0KICApDQogIA0KICByZXR1cm4oY29vcmRpbmF0ZXMpDQp9DQoNCg0KbXVuaWNpcGFsaXR5IDwtICJBY2FqZXRlIg0KbG9jYWxpdHkgPC0gIlNhbnRhIElzYWJlbCBUZXBldHphbGEiDQoNCnJlZF9wb2ludCA8LSBleHRyYWN0X2Nvb3JkaW5hdGVzKHB1ZWJfbm9ybSwgbXVuaWNpcGFsaXR5LCBsb2NhbGl0eSkgfD4gDQogIHNsaWNlKDEpDQoNCiMgcmVkX3BvaW50IDwtIGRhdGEuZnJhbWUobG9uZyA9IC05OC4yMDM1LCBsYXQgPSAxOS4wNDE0KQ0KDQpmaWx0ZXJlZF9nZW9qc29uIDwtIGdlb2pzb25fZmlsZSB8PiANCiAgZmlsdGVyKG5hbWUgPT0gIlB1ZWJsYSIpDQoNCmdncGxvdCgpICsNCiAgZ2VvbV9wb2x5Z29uKGRhdGEgPSBmaWx0ZXJlZF9nZW9qc29uLA0KICAgICAgICAgICAgICAgYWVzKHggPSBsb25nLCB5ID0gbGF0LCBncm91cCA9IGdyb3VwKSwNCiAgICAgICAgICAgICAgIGZpbGwgPSAibGlnaHRncmF5IiwgY29sb3IgPSAid2hpdGUiKSArDQogIGdlb21fcG9pbnQoZGF0YSA9IHJlZF9wb2ludCwgYWVzKHggPSBsb25nLCB5ID0gbGF0KSwgY29sb3IgPSAicmVkIiwgc2l6ZSA9IDMpICsNCiAgdGhlbWVfdm9pZCgpICsNCiAgY29vcmRfbWFwKCkNCmBgYA0KDQojIyMgUG9wdWxhdGlvbiBncmFwaA0KDQpgYGB7cn0NCnB1ZWJfbm9ybQ0KYGBgDQoNCiMjIyBHZXR0aW5nIGNvbHVtbiBuYW1lcw0KDQpgYGB7cn0NCmNvbHVtbl9uYW1lcyA8LSBuYW1lcyhwdWViX25vcm0pDQpjb2x1bW5fbmFtZXMNCmBgYA0KDQojIyMgR2V0dGluZyBjb2x1bW4gbmFtZXMgdGhhdCBoYXZlIHRvIGRvIHdpdGggcG9wdWxhdGlvbiBhZ2UgY29ob3J0cyAoTWFzY3VsaW5lL0ZlbWluaW5lKQ0KDQpgYGB7cn0NCm1hdGNoaW5nX2NvbHVtbnMgPC0gZ3JlcCgiXlBfLipbTUZdJCIsIGNvbHVtbl9uYW1lcywgdmFsdWUgPSBUUlVFKQ0KbWF0Y2hpbmdfY29sdW1ucw0KYGBgDQoNCiMjIyBTZXBhcmF0ZSBieSBzZXgNCg0KYGBge3J9DQplbmRpbmdfaW5fTSA8LSBjaGFyYWN0ZXIoMCkNCmVuZGluZ19pbl9GIDwtIGNoYXJhY3RlcigwKQ0KDQpmb3IgKGNvbF9uYW1lIGluIG1hdGNoaW5nX2NvbHVtbnMpIHsNCiAgaWYgKGVuZHNXaXRoKGNvbF9uYW1lLCAiTSIpKSB7DQogICAgZW5kaW5nX2luX00gPC0gYyhlbmRpbmdfaW5fTSwgY29sX25hbWUpDQogIH0gZWxzZSBpZiAoZW5kc1dpdGgoY29sX25hbWUsICJGIikpIHsNCiAgICBlbmRpbmdfaW5fRiA8LSBjKGVuZGluZ19pbl9GLCBjb2xfbmFtZSkNCiAgfQ0KfQ0KDQpwcmludCgiQ29sdW1uIG5hbWVzIGVuZGluZyBpbiBNOiIpDQpwcmludChlbmRpbmdfaW5fTSkNCg0KcHJpbnQoIkNvbHVtbiBuYW1lcyBlbmRpbmcgaW4gRjoiKQ0KcHJpbnQoZW5kaW5nX2luX0YpDQpgYGANCg0KYGBge3J9DQpjb2hvcnRfbmFtZXNfbSA8LSBjKCJQXzBBNF9NIiwNCiAgICAgICAgICAgICAgICAgICAgIlBfNUE5X00iLA0KICAgICAgICAgICAgICAgICAgICAiUF8xMEExNF9NIiwNCiAgICAgICAgICAgICAgICAgICAgIlBfMTVBMTlfTSIsDQogICAgICAgICAgICAgICAgICAgICJQXzIwQTI0X00iLA0KICAgICAgICAgICAgICAgICAgICAiUF8yNUEyOV9NIiwNCiAgICAgICAgICAgICAgICAgICAgIlBfMzBBMzRfTSIsDQogICAgICAgICAgICAgICAgICAgICJQXzM1QTM5X00iLA0KICAgICAgICAgICAgICAgICAgICAiUF80MEE0NF9NIiwNCiAgICAgICAgICAgICAgICAgICAgIlBfNDVBNDlfTSIsDQogICAgICAgICAgICAgICAgICAgICJQXzUwQTU0X00iLA0KICAgICAgICAgICAgICAgICAgICAiUF81NUE1OV9NIiwNCiAgICAgICAgICAgICAgICAgICAgIlBfNjBBNjRfTSIsDQogICAgICAgICAgICAgICAgICAgICJQXzY1QTY5X00iLA0KICAgICAgICAgICAgICAgICAgICAiUF83MEE3NF9NIiwNCiAgICAgICAgICAgICAgICAgICAgIlBfNzVBNzlfTSIsDQogICAgICAgICAgICAgICAgICAgICJQXzgwQTg0X00iLA0KICAgICAgICAgICAgICAgICAgICAiUF84NVlNQVNfTSIpDQoNCmNvaG9ydF9uYW1lc19mIDwtIGMoIlBfMEE0X0YiLA0KICAgICAgICAgICAgICAgICAgICAiUF81QTlfRiIsDQogICAgICAgICAgICAgICAgICAgICJQXzEwQTE0X0YiLA0KICAgICAgICAgICAgICAgICAgICAiUF8xNUExOV9GIiwNCiAgICAgICAgICAgICAgICAgICAgIlBfMjBBMjRfRiIsDQogICAgICAgICAgICAgICAgICAgICJQXzI1QTI5X0YiLA0KICAgICAgICAgICAgICAgICAgICAiUF8zMEEzNF9GIiwNCiAgICAgICAgICAgICAgICAgICAgIlBfMzVBMzlfRiIsDQogICAgICAgICAgICAgICAgICAgICJQXzQwQTQ0X0YiLA0KICAgICAgICAgICAgICAgICAgICAiUF80NUE0OV9GIiwNCiAgICAgICAgICAgICAgICAgICAgIlBfNTBBNTRfRiIsDQogICAgICAgICAgICAgICAgICAgICJQXzU1QTU5X0YiLA0KICAgICAgICAgICAgICAgICAgICAiUF82MEE2NF9GIiwNCiAgICAgICAgICAgICAgICAgICAgIlBfNjVBNjlfRiIsIA0KICAgICAgICAgICAgICAgICAgICAiUF83MEE3NF9GIiwNCiAgICAgICAgICAgICAgICAgICAgIlBfNzVBNzlfRiIsDQogICAgICAgICAgICAgICAgICAgICJQXzgwQTg0X0YiLCANCiAgICAgICAgICAgICAgICAgICAgIlBfODVZTUFTX0YiKQ0KDQoNCg0KbXVuaWNpcGFsaXR5IDwtICJBY2FqZXRlIg0KbG9jYWxpdHkgPC0gIlNhbiBKYXZpZXIiDQoNCnB1ZWJfbm9ybV9maWx0IDwtIHB1ZWJfbm9ybSB8PiANCiAgICBmaWx0ZXIoTk9NX01VTiA9PSBtdW5pY2lwYWxpdHksIE5PTV9MT0MgPT0gbG9jYWxpdHkpDQoNCmNvaG9ydF9jb3VudHNfbSA8LSBhcy5udW1lcmljKHB1ZWJfbm9ybV9maWx0WzEsY29ob3J0X25hbWVzX21dKQ0KY29ob3J0X2NvdW50c19mIDwtIGFzLm51bWVyaWMocHVlYl9ub3JtX2ZpbHRbMSxjb2hvcnRfbmFtZXNfZl0pDQoNCmRhdGEgPC0gdGliYmxlKA0KICBDb2hvcnQgPSBjKGNvaG9ydF9uYW1lc19tLCBjb2hvcnRfbmFtZXNfZiksDQogIENvdW50ID0gYyhjb2hvcnRfY291bnRzX20sIGNvaG9ydF9jb3VudHNfZiksDQogIFNleCA9IHJlcChjKCJNYWxlIiwgIkZlbWFsZSIpLCBlYWNoID0gbGVuZ3RoKGNvaG9ydF9uYW1lc19tKSkNCikNCg0KIyBQbG90dGluZyBwb3B1bGF0aW9uIHB5cmFtaWQNCmdncGxvdChkYXRhLCBhZXMoeCA9IHJlb3JkZXIoQ29ob3J0LCAtQ291bnQpLCB5ID0gQ291bnQsIGZpbGwgPSBTZXgpKSArDQogIGdlb21fYmFyKHN0YXQgPSAiaWRlbnRpdHkiLCBwb3NpdGlvbiA9ICJpZGVudGl0eSIpICsNCiAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gYygiYmx1ZSIsICJwaW5rIikpICsgIA0KICBjb29yZF9mbGlwKCkgKyAgDQogIGxhYnModGl0bGUgPSAiUG9wdWxhdGlvbiBQeXJhbWlkIiwNCiAgICAgICB4ID0gIlBvcHVsYXRpb24gQ291bnQiLA0KICAgICAgIHkgPSAiQWdlIENvaG9ydCIsDQogICAgICAgZmlsbCA9ICJTZXgiKSArDQogIHRoZW1lX21pbmltYWwoKSAgDQoNCmBgYA0KDQpgYGB7cn0NCm5ld19hZ2VzIDwtIGMoIjAtNCIsDQogICAgICAgICAgICAgICAgICI1LTkiLA0KICAgICAgICAgICAgICAgICAiMTAtMTQiLA0KICAgICAgICAgICAgICAgICAiMTUtMTkiLA0KICAgICAgICAgICAgICAgICAiMjAtMjQiLA0KICAgICAgICAgICAgICAgICAiMjUtMjkiLCANCiAgICAgICAgICAgICAgICAgIjMwLTM0IiwgDQogICAgICAgICAgICAgICAgICIzNS0zOSIsIA0KICAgICAgICAgICAgICAgICAiNDAtNDQiLCANCiAgICAgICAgICAgICAgICAgIjQ1LTQ5IiwNCiAgICAgICAgICAgICAgICAgIjUwLTU0IiwNCiAgICAgICAgICAgICAgICAgIjU1LTU5IiwNCiAgICAgICAgICAgICAgICAgIjYwLTY0IiwgDQogICAgICAgICAgICAgICAgICI2NS02OSIsDQogICAgICAgICAgICAgICAgICI3MC03NCIsIA0KICAgICAgICAgICAgICAgICAiNzUtNzkiLCANCiAgICAgICAgICAgICAgICAgIjgwLTg0IiwgDQogICAgICAgICAgICAgICAgICI4NSsiKQ0KDQpkYXRhIDwtIHRpYmJsZSgNCiAgQWdlID0gcGFzdGUwKG5ld19hZ2VzKSwNCiAgTWFsZSA9IHNhbXBsZSgyMDA6MTAwMCwgbGVuZ3RoKGNvaG9ydF9uYW1lc19tKSwgcmVwbGFjZSA9IFRSVUUpLA0KICBGZW1hbGUgPSBzYW1wbGUoMjAwOjEwMDAsIGxlbmd0aChjb2hvcnRfbmFtZXNfZiksIHJlcGxhY2UgPSBUUlVFKQ0KKQ0KDQpkYXRhX2xvbmcgPC0gcGl2b3RfbG9uZ2VyKA0KICBkYXRhLCANCiAgY29scyA9IGMoTWFsZSwgRmVtYWxlKSwgDQogIG5hbWVzX3RvID0gIlNleCIsIA0KICB2YWx1ZXNfdG8gPSAiUG9wdWxhdGlvbiINCikNCg0KYmFzaWNfcGxvdCA8LSBnZ3Bsb3QoZGF0YV9sb25nLCBhZXMoeCA9IEFnZSwgeSA9IGlmZWxzZShTZXggPT0gIk1hbGUiLCAtUG9wdWxhdGlvbiwgUG9wdWxhdGlvbiksIGZpbGwgPSBTZXgpKSArDQogIGdlb21fYmFyKHN0YXQgPSAiaWRlbnRpdHkiKSArDQogIHNjYWxlX3lfY29udGludW91cyhsYWJlbHMgPSBhYnMsIGxpbWl0cyA9IG1heChkYXRhX2xvbmckUG9wdWxhdGlvbikgKiBjKC0xLCAxKSkgKw0KICBjb29yZF9mbGlwKCkgKw0KICB0aGVtZV9taW5pbWFsKCkgKw0KICBsYWJzKHggPSAiQWdlIiwgeSA9ICJQb3B1bGF0aW9uIiwgZmlsbCA9ICJTZXgiLCB0aXRsZSA9ICJQb3B1bGF0aW9uIFB5cmFtaWQiKQ0KDQpiYXNpY19wbG90DQpgYGANCg0KIyMjIENvbXBsZXRlIHBpcGVsaW5lDQoNCmBgYHtyfQ0KY2Vuc3VzX2RhdGFzZXQgPC0gb3Blbl9kYXRhc2V0KGhlcmUoImRhdGEiLCAicHJvY2Vzc2VkIiwgInBhcnF1ZXRfZGF0YV9jb29yZHMiKSkNCg0KDQpwdWViX25vcm0gPC0gY2Vuc3VzX2RhdGFzZXQgfD4NCiAgICBmaWx0ZXIoTk9NX0VOVD09IlB1ZWJsYSIpIHw+IA0KICAgIGNvbGxlY3QoKQ0KDQptdW5pY2lwYWxpdHkgPC0gIkFjYWpldGUiDQpsb2NhbGl0eSA8LSAiU2FuIEphdmllciINCg0KcHVlYl9ub3JtX2ZpbHQgPC0gcHVlYl9ub3JtIHw+IA0KICAgIGZpbHRlcihOT01fTVVOID09IG11bmljaXBhbGl0eSwgTk9NX0xPQyA9PSBsb2NhbGl0eSkNCg0KDQpjb2hvcnRfbmFtZXNfbSA8LSBjKCJQXzBBNF9NIiwNCiAgICAgICAgICAgICAgICAgICAgIlBfNUE5X00iLA0KICAgICAgICAgICAgICAgICAgICAiUF8xMEExNF9NIiwNCiAgICAgICAgICAgICAgICAgICAgIlBfMTVBMTlfTSIsDQogICAgICAgICAgICAgICAgICAgICJQXzIwQTI0X00iLA0KICAgICAgICAgICAgICAgICAgICAiUF8yNUEyOV9NIiwNCiAgICAgICAgICAgICAgICAgICAgIlBfMzBBMzRfTSIsDQogICAgICAgICAgICAgICAgICAgICJQXzM1QTM5X00iLA0KICAgICAgICAgICAgICAgICAgICAiUF80MEE0NF9NIiwNCiAgICAgICAgICAgICAgICAgICAgIlBfNDVBNDlfTSIsDQogICAgICAgICAgICAgICAgICAgICJQXzUwQTU0X00iLA0KICAgICAgICAgICAgICAgICAgICAiUF81NUE1OV9NIiwNCiAgICAgICAgICAgICAgICAgICAgIlBfNjBBNjRfTSIsDQogICAgICAgICAgICAgICAgICAgICJQXzY1QTY5X00iLA0KICAgICAgICAgICAgICAgICAgICAiUF83MEE3NF9NIiwNCiAgICAgICAgICAgICAgICAgICAgIlBfNzVBNzlfTSIsDQogICAgICAgICAgICAgICAgICAgICJQXzgwQTg0X00iLA0KICAgICAgICAgICAgICAgICAgICAiUF84NVlNQVNfTSIpDQoNCmNvaG9ydF9uYW1lc19mIDwtIGMoIlBfMEE0X0YiLA0KICAgICAgICAgICAgICAgICAgICAiUF81QTlfRiIsDQogICAgICAgICAgICAgICAgICAgICJQXzEwQTE0X0YiLA0KICAgICAgICAgICAgICAgICAgICAiUF8xNUExOV9GIiwNCiAgICAgICAgICAgICAgICAgICAgIlBfMjBBMjRfRiIsDQogICAgICAgICAgICAgICAgICAgICJQXzI1QTI5X0YiLA0KICAgICAgICAgICAgICAgICAgICAiUF8zMEEzNF9GIiwNCiAgICAgICAgICAgICAgICAgICAgIlBfMzVBMzlfRiIsDQogICAgICAgICAgICAgICAgICAgICJQXzQwQTQ0X0YiLA0KICAgICAgICAgICAgICAgICAgICAiUF80NUE0OV9GIiwNCiAgICAgICAgICAgICAgICAgICAgIlBfNTBBNTRfRiIsDQogICAgICAgICAgICAgICAgICAgICJQXzU1QTU5X0YiLA0KICAgICAgICAgICAgICAgICAgICAiUF82MEE2NF9GIiwNCiAgICAgICAgICAgICAgICAgICAgIlBfNjVBNjlfRiIsIA0KICAgICAgICAgICAgICAgICAgICAiUF83MEE3NF9GIiwNCiAgICAgICAgICAgICAgICAgICAgIlBfNzVBNzlfRiIsDQogICAgICAgICAgICAgICAgICAgICJQXzgwQTg0X0YiLCANCiAgICAgICAgICAgICAgICAgICAgIlBfODVZTUFTX0YiKQ0KDQoNCg0KbmV3X2FnZXMgPC0gYygiMC00IiwNCiAgICAgICAgICAgICAgICAgIjUtOSIsDQogICAgICAgICAgICAgICAgICIxMC0xNCIsDQogICAgICAgICAgICAgICAgICIxNS0xOSIsDQogICAgICAgICAgICAgICAgICIyMC0yNCIsDQogICAgICAgICAgICAgICAgICIyNS0yOSIsIA0KICAgICAgICAgICAgICAgICAiMzAtMzQiLCANCiAgICAgICAgICAgICAgICAgIjM1LTM5IiwgDQogICAgICAgICAgICAgICAgICI0MC00NCIsIA0KICAgICAgICAgICAgICAgICAiNDUtNDkiLA0KICAgICAgICAgICAgICAgICAiNTAtNTQiLA0KICAgICAgICAgICAgICAgICAiNTUtNTkiLA0KICAgICAgICAgICAgICAgICAiNjAtNjQiLCANCiAgICAgICAgICAgICAgICAgIjY1LTY5IiwNCiAgICAgICAgICAgICAgICAgIjcwLTc0IiwgDQogICAgICAgICAgICAgICAgICI3NS03OSIsIA0KICAgICAgICAgICAgICAgICAiODAtODQiLCANCiAgICAgICAgICAgICAgICAgIjg1KyIpDQoNCg0KZGF0YSA8LSB0aWJibGUoDQogIEFnZSA9IHBhc3RlMChuZXdfYWdlcyksDQogIE1hbGUgPSBhcy5udW1lcmljKHB1ZWJfbm9ybV9maWx0WzEsY29ob3J0X25hbWVzX21dKSwNCiAgRmVtYWxlID0gYXMubnVtZXJpYyhwdWViX25vcm1fZmlsdFsxLGNvaG9ydF9uYW1lc19mXSkNCikNCg0KZGF0YV9sb25nIDwtIHBpdm90X2xvbmdlcigNCiAgZGF0YSwgDQogIGNvbHMgPSBjKE1hbGUsIEZlbWFsZSksIA0KICBuYW1lc190byA9ICJTZXgiLCANCiAgdmFsdWVzX3RvID0gIlBvcHVsYXRpb24iDQopDQpiYXNpY19wbG90IDwtIGdncGxvdChkYXRhX2xvbmcsIGFlcyh4ID0gQWdlLCB5ID0gaWZlbHNlKFNleCA9PSAiTWFsZSIsIC1Qb3B1bGF0aW9uLCBQb3B1bGF0aW9uKSwgZmlsbCA9IFNleCkpICsNCiAgZ2VvbV9iYXIoc3RhdCA9ICJpZGVudGl0eSIpICsNCiAgc2NhbGVfeV9jb250aW51b3VzKGxhYmVscyA9IGFicywgbGltaXRzID0gbWF4KGRhdGFfbG9uZyRQb3B1bGF0aW9uKSAqIGMoLTEsIDEpKSArDQogIGNvb3JkX2ZsaXAoKSArDQogIHRoZW1lX21pbmltYWwoKSArDQogIGxhYnMoeCA9ICJBZ2UiLCB5ID0gIlBvcHVsYXRpb24iLCBmaWxsID0gIlNleCIsIHRpdGxlID0gIlBvcHVsYXRpb24gUHlyYW1pZCIpDQoNCmJhc2ljX3Bsb3QNCmBgYA0KDQojIyMgQ2FyZA0KDQpgYGB7cn0NCiMgY2FyZCA8LSBjZW5zdXNfZGF0YXNldCB8PiAgDQojICAgICBmaWx0ZXIoDQojICAgICAgIE5PTV9FTlQgPT0gIlB1ZWJsYSIsDQojICAgICAgIE5PTV9NVU4gPT0gIkFjYXRlbm8iLA0KIyAgICAgICBOT01fTE9DID09ICJTYW50YSBBbmRyZWEiDQojICAgICApIHw+IA0KIyAgIGNvbGxlY3QoKQ0KICAgIA0KICAgIHRvdGFsX3BvcHVsYXRpb24gPC0gYXMubnVtZXJpYyhjYXJkWzEsIGMoIlBPQlRPVCIpXSwgbmEucm0gPSBUUlVFKQ0KICAgIHBhc3RlKCJUb3RhbCBQb3B1bGF0aW9uOiIsIHRvdGFsX3BvcHVsYXRpb24pDQpgYGANCg0KIyMjIFBpZQ0KDQpgYGB7cn0NCnRvdCA8LSBjZW5zdXNfZGF0YXNldCB8Pg0KICAgIGZpbHRlcihOT01fRU5UPT0iVG90YWwgbmFjaW9uYWwiKSB8PiANCiAgICBjb2xsZWN0KCkNCg0KdG90DQpgYGANCg0KYGBge3J9DQojIG9yaWdpbiA8LSBjZW5zdXNfZGF0YXNldCB8PiAgDQojICAgICAgZmlsdGVyKA0KIyAgICAgICBOT01fRU5UID09ICJQdWVibGEiLA0KIyAgICAgICBOT01fTVVOID09ICJBY2F0ZW5vIiwNCiMgICAgICAgTk9NX0xPQyA9PSAiU2FudGEgQW5kcmVhIg0KIyAgICAgKSB8Pg0KIyAgIGNvbGxlY3QoKQ0KICAgIA0KdG90DQogICAgDQogICAgIyBFeHRyYWN0IGJpcnRoIGRhdGENCiAgICBiaXJ0aF9sb2NhbCA8LSBhcy5udW1lcmljKHRvdFsxLCAiUE5BQ0VOVCJdKQ0KICAgIGJpcnRoX2Fub3RoZXIgPC0gYXMubnVtZXJpYyh0b3RbMSwgIlBOQUNPRSJdKQ0KICAgIA0KICAgICMgRGVidWdnaW5nIG91dHB1dA0KICAgIHByaW50KHBhc3RlKCJCaXJ0aCBMb2NhbDoiLCBiaXJ0aF9sb2NhbCkpDQogICAgcHJpbnQocGFzdGUoIkJpcnRoIEFub3RoZXI6IiwgYmlydGhfYW5vdGhlcikpDQogICAgDQogICAgIyBDcmVhdGUgcmF0aW8gZGF0YWZyYW1lDQogICAgcmF0aW9fZGYgPC0gdGliYmxlKA0KICAgICAgQ2F0ZWdvcnkgPSBjKCJMb2NhbCIsICJPdGhlciIpLA0KICAgICAgUmF0aW8gPSBjKGJpcnRoX2xvY2FsLCBiaXJ0aF9hbm90aGVyKQ0KICAgICkNCiAgICANCiAgICAjIENhbGN1bGF0ZSBwZXJjZW50YWdlcw0KICAgIHJhdGlvX2RmJFBlcmNlbnRhZ2UgPC0gcmF0aW9fZGYkUmF0aW8gLyBzdW0ocmF0aW9fZGYkUmF0aW8pICogMTAwDQogICAgDQogICAgIyBQbG90IHRoZSBwaWUgY2hhcnQNCiAgICBnZyA8LSBnZ3Bsb3QocmF0aW9fZGYsIGFlcyh4ID0gIiIsIHkgPSBSYXRpbywgZmlsbCA9IENhdGVnb3J5KSkgKw0KICAgICAgZ2VvbV9iYXIoc3RhdCA9ICJpZGVudGl0eSIsIHdpZHRoID0gMSkgKw0KICAgICAgY29vcmRfcG9sYXIodGhldGEgPSAieSIpICsNCiAgICAgIHRoZW1lX3ZvaWQoKSArDQogICAgICB0aGVtZShsZWdlbmQucG9zaXRpb24gPSAiYm90dG9tIikgKw0KICAgICAgc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gYygiIzAwQkZDNCIsICIjRjg3NjZEIikpICsNCiAgICAgIGdlb21fdGV4dChhZXMobGFiZWwgPSBwYXN0ZTAocm91bmQoUGVyY2VudGFnZSksICIlIikpLCANCiAgICAgICAgICAgICAgICBwb3NpdGlvbiA9IHBvc2l0aW9uX3N0YWNrKHZqdXN0ID0gMC41KSwNCiAgICAgICAgICAgICAgICBzaXplID0gNSwgY29sb3IgPSAid2hpdGUiLCBmb250ZmFjZSA9ICJib2xkIikNCiAgICANCiAgICBnZw0KICAgIA0KYGBgDQo=